﻿using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using IntraVision.Web.Toolkit;

namespace IntraVision.Web.Filter
{
    public class NumericFilterCondition<TEntity> : IFilterCondition<TEntity>
        where TEntity: class, new()
    {
        string _Column;
        string _Caption;
        bool _Nullable;
        int _Value1;
        int _Value2;
        string _Values = "";
        int _Type = 0;

        public string Column
        {
            get { return _Column; }
            set { _Column = value; }
        }

        public bool Active
        {
            get { return _Type > 0; }
        }

        public string SafeColumn
        {
            get { return Column.Replace('.', '_'); }
        }

        string[] _Types = { HTMLHelper.Resource("Filter", "Equal", "равно"), HTMLHelper.Resource("Filter", "Greater", "больше"), HTMLHelper.Resource("Filter", "Lower", "меньше"), HTMLHelper.Resource("Filter", "IsIn", "входит в"), HTMLHelper.Resource("Filter", "Between", "между"), HTMLHelper.Resource("Filter", "Defined", "задано"), HTMLHelper.Resource("Filter", "Undefined", "не задано") };

        public NumericFilterCondition(string column, string caption, bool nullable)
        {
            _Column = column;
            _Caption = caption;
            _Nullable = nullable;
        }

        public NumericFilterCondition(string column, string caption)
            : this(column, caption, false)
        {
        }

        #region IFilterCondition<TEntity> Members

        public IQueryable<TEntity> Filter(IQueryable<TEntity> list)
        {
            string nullable = _Nullable ? ".Value" : "";

            if (_Type == 6) return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} != null", _Column, nullable));
            if (_Type == 7) return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} == null", _Column, nullable));

            switch (_Type)
            {
                case 1:
                    return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} == @0", _Column, nullable), _Value1);
                case 2:
                    return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} > @0", _Column, nullable), _Value1);
                case 3:
                    return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} < @0", _Column, nullable), _Value1);
                case 4:
                    int[] ids = RequestHelper.GetIdsFromString(_Values);
                    StringBuilder sb = new StringBuilder();
                    foreach (int id in ids)
                    {
                        sb.Append(sb.Length > 0 ? " || " : "(");
                        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}=={2}", _Column, nullable, id);
                    }
                    sb.Append(")");
                    return list.Where(sb.ToString());
                case 5:
                    return list.Where(string.Format(CultureInfo.InvariantCulture, "{0}{1} >= @0 && {0}{1} <= @1", _Column, nullable), _Value1, _Value2);
            }
            return list;
        }

        #endregion

        #region IFilterCondition Members

        public string Render()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(string.Format(CultureInfo.InvariantCulture, @"<div class=""filterfield""><table width=""100%""><tr><td class=""tdlabel""><label for=""flt1{0}"">{1}</label></td>", SafeColumn, _Caption));
            sb.Append(string.Format(CultureInfo.InvariantCulture, @"<td class=""tdcondition""><select class=""flttype fttnumeric"" id=""ftt{0}"" name=""ftt{0}""><option value=""0"" />", SafeColumn));
            for (int i = 0; i < _Types.Length; i++)
                sb.Append(string.Format(CultureInfo.InvariantCulture, @"<option value=""{0}"" {2}>{1}</option>", i + 1, _Types[i], ((_Type == (i + 1)) ? " selected" : "")));
            sb.Append("</select></td>");
            sb.Append(string.Format(CultureInfo.InvariantCulture, @"<td class=""tdvalue""><input class=""numeric {6} {7}"" type=""text"" id=""flt1{0}"" name=""flt1{0}"" value=""{2}"" /> <span class=""numeric2 {4}""> {6} <input class=""numeric"" type=""text"" id=""flt2{0}"" name=""flt2{0}"" value=""{3}"" /></span><span class=""numeric3 {5}"">{7}</span></td></tr></table></div>"
                , SafeColumn, _Caption, (_Type > 0 && _Type != 6 && _Type != 7) ? _Value1.ToString(CultureInfo.InvariantCulture) : "", (_Type == 5) ? _Value2.ToString(CultureInfo.InvariantCulture) : "", (_Type == 5) ? "" : "hidden", (_Type == 4) ? "" : "hidden", (_Type == 4) ? "width150px" : "", (_Type == 6 || _Type == 7) ? "hidden" : "", HTMLHelper.Resource("Filter", "And", "и"), HTMLHelper.Resource("Filter", "NumericSample", @"Через запятую, например: ""27,33,45""")));
            return sb.ToString();
        }

        public void Init(NameValueCollection req)
        {
            if (!string.IsNullOrEmpty(req["ftt" + SafeColumn]))
                Int32.TryParse(req["ftt" + SafeColumn], out _Type);
            if (_Type == 4)
                _Values = req["flt1" + SafeColumn];
            else
            {
                if (!string.IsNullOrEmpty(req["flt1" + SafeColumn]))
                    Int32.TryParse(req["flt1" + SafeColumn], out _Value1);
                if (!string.IsNullOrEmpty(req["flt2" + _Column]))
                    Int32.TryParse(req["flt2" + SafeColumn], out _Value2);
            }
        }

        #endregion

        public override string ToString()
        {
            if (_Type <= 0) return string.Empty;
            if (_Type == 4) return string.Format("ftt{0}={1}&flt1{0}={2}", SafeColumn, _Type, _Values);
            return string.Format("ftt{0}={1}&flt1{0}={2}&flt2{0}={3}", SafeColumn, _Type, _Value1, _Value2);
        }
    }
}
